<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>Document</title>
		<style>
			body {
				font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
				width: 700px;
				height: 500px;
				position: relative;
			}

			svg {
				width: 100%;
				height: 100%;
			}

			path.slice {
				stroke-width: 2px;
			}

			polyline {
				opacity: 0.3;
				stroke: black;
				stroke-width: 0.4px;
				fill: none;
			}
		</style>
		<script src="http://d3js.org/d3.v3.min.js"></script>
	</head>
	<body>
		<button class="randomize">随机</button>
	</body>
	<script>
		// 结构布局
		const svg = d3.select("body").append("svg").append("g");

		svg.append("g").attr("class", "slices");
		svg.append("g").attr("class", "labels");
		svg.append("g").attr("class", "lines");

		const width = 700,
			height = 450,
			radius = Math.min(width, height) / 2;

		svg.attr(
			"transform",
			"translate(" + width / 2 + "," + height / 2 + ")"
		);
        const data = [
  { label: 'Item 1', value: 10 },
  { label: 'Item 2', value: 20 },
  { label: 'Item 3', value: 30 }
];
		const pie = d3.layout
			.pie()
			.sort(null)
			.value(function (d) {
				return d.value;
			});

	
        

		const arc = d3.svg
			.arc()
			.outerRadius(radius * 0.8)
			.innerRadius(radius * 0.4);

		const outerArc = d3.svg
			.arc()
			.innerRadius(radius * 0.9)
			.outerRadius(radius * 0.9);

		const key = function (d) {
			return d.data.label;
		};

		const color = d3.scale
			.ordinal()
			.domain([
				"Rose",
				"Sunflower",
				"Tulip",
				"Orchid",
				"Lily",
				"Jasmine",
				"Lavender",
				"Cherry Blossom",
				"Maple",
				"Bamboo",
				"Cactus",
			])
			.range([
				"#142403 ",
				"#32520e ",
				"#226232 ",
				"#207134",
				"#2C9747 ",
				"#36BF59 ",
				"#57D177",
				"#7FDD97 ",
				"#A6E8B7",
				"#a6f5ba",
				"#f2fce5",
			]);

		function randomData() {
			const labels = color.domain();
			return labels.map(function (label) {
				return { label: label, value: Math.random() };
			});
		}

		change(randomData());

		function change(data) {
			/* 生成环形 */
			const slice = svg
				.select(".slices")
				.selectAll("path.slice")
				.data(pie(data), key);

			slice
				.enter()
				.insert("path")
				.style("fill", function (d) {
					return color(d.data.label);
				})
				.attr("class", "slice");

			slice
				.transition()
				.duration(1000)
				.attrTween("d", function (d) {
					this._current = this._current || d;
					const interpolate = d3.interpolate(this._current, d);
					this._current = interpolate(0);
					return function (t) {
						return arc(interpolate(t));
					};
				});

			slice.exit().remove();

			// ....

			/* 生成标注 */
			const text = svg
				.select(".labels")
				.selectAll("text")
				.data(pie(data), key);

			text.enter()
				.append("text")
				.attr("dy", ".35em")
				.text(function (d) {
					return d.data.label;
				});

			function midAngle(d) {
				return d.startAngle + (d.endAngle - d.startAngle) / 2;
			}

			text.transition()
				.duration(1000)
				.attrTween("transform", function (d) {
					this._current = this._current || d;
					const interpolate = d3.interpolate(this._current, d);
					this._current = interpolate(0);
					return function (t) {
						const d2 = interpolate(t);
						const pos = outerArc.centroid(d2);
						pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1);
						return "translate(" + pos + ")";
					};
				})
				.styleTween("text-anchor", function (d) {
					this._current = this._current || d;
					const interpolate = d3.interpolate(this._current, d);
					this._current = interpolate(0);
					return function (t) {
						const d2 = interpolate(t);
						return midAngle(d2) < Math.PI ? "start" : "end";
					};
				});

			text.exit().remove();
		}

		/* 生成引线 */
		const polyline = svg
			.select(".lines")
			.selectAll("polyline")
			.data(pie(data), key);
 
        
		polyline.enter().append("polyline");
        
		polyline
			.transition()
			.duration(1000)
			.attrTween("points", function (d) {
				this._current = this._current || d;
				const interpolate = d3.interpolate(this._current, d);
				this._current = interpolate(0);
				return function (t) {
					const d2 = interpolate(t);
					const pos = outerArc.centroid(d2);
					pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
					return [arc.centroid(d2), outerArc.centroid(d2), pos];
				};
			});

		polyline.exit().remove();
	</script>
</html>
